package tom.spring.cloud.gateway;

import lombok.extern.slf4j.Slf4j;
import org.reactivestreams.Publisher;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.web.reactive.WebFluxProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.gateway.filter.factory.rewrite.RewriteFunction;
import org.springframework.cloud.gateway.route.RouteLocator;
import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
import org.springframework.http.MediaType;
import org.springframework.http.codec.ServerCodecConfigurer;
import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity;
import org.springframework.security.config.web.server.ServerHttpSecurity;
import org.springframework.security.web.server.SecurityWebFilterChain;
import org.springframework.web.reactive.config.EnableWebFlux;
import org.springframework.web.reactive.config.WebFluxConfigurer;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.util.HashMap;
import java.util.Map;

/**
 * 基于配置的gateway, 修改请求体和响应体, profiles: default
 * http://localhost:8090/actuator/gateway/routes
 * 屏蔽spring-security
 * @author ZHUFEIFEI
 */
@Slf4j
@EnableWebFlux
@EnableDiscoveryClient
@SpringBootApplication
@ComponentScan(
        excludeFilters = {
        @ComponentScan.Filter(type = FilterType.REGEX,
                pattern = "tom\\.spring\\.cloud\\.gateway\\..*"
        )
})
public class Gateway06Application {

    public static void main(String[] args) {
        SpringApplication.run(Gateway06Application.class, args);
    }



    @Bean
    public RouteLocator routes(RouteLocatorBuilder builder) {
        return builder.routes()
                .route("rewrite_request_response_obj"
                        , r -> r.path("/hello").filters(
                                f -> f.setRequestHeader("a", "b")
                                        //重写请求体
                                        .modifyRequestBody(
                                                String.class, String.class, MediaType.APPLICATION_JSON_UTF8_VALUE,
                                                new RewriteFunction<String, String>() {
                                                    @Override
                                                    public Publisher<String> apply(ServerWebExchange serverWebExchange, String s) {
                                                        return Mono.just("gateway-" + s);
                                                    }
                                                }
                                        )
                                        //重写响应体
                                        .modifyResponseBody(String.class, String.class, MediaType.APPLICATION_JSON_UTF8_VALUE,
                                                ((serverWebExchange, s) -> Mono.just("gateway-"+s))
                                        )
                        ).uri("http://localhost:8021")
                ).build();
    }




    @Configuration
    @EnableConfigurationProperties(WebFluxProperties.class)
    class MyWebFluxConfigurer implements WebFluxConfigurer {

        @Override
        public void configureHttpMessageCodecs(ServerCodecConfigurer configurer) {
            //打印header详情
            configurer.defaultCodecs().enableLoggingRequestDetails(true);
        }
    }

    @EnableWebFluxSecurity
    class MyFluxSecurityConfig {

        @Bean
        public SecurityWebFilterChain securityWebFilterChain(ServerHttpSecurity http) {
            //允许所有请求
            return http.authorizeExchange().anyExchange().permitAll().and().build();
        }

    }
}
